package com.atguigu.guli.service.ucenter.controller.api;


import com.atguigu.guli.common.util.HttpClientUtils;
import com.atguigu.guli.service.base.exception.GuLiException;
import com.atguigu.guli.service.base.helper.JwtHelper;
import com.atguigu.guli.service.base.helper.JwtInfo;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.ucenter.entity.Member;
import com.atguigu.guli.service.ucenter.service.MemberService;
import com.atguigu.guli.service.ucenter.util.UcenterProperties;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

//@CrossOrigin
@Controller//注意这里没有配置 @RestController
@RequestMapping("/api/ucenter/wx")
@Slf4j
public class ApiWxController {
    @Autowired
    private UcenterProperties ucenterProperties;

    @Autowired
    private MemberService memberService;

    /**
     * 获取登录二维码地址
     *
     * @return
     */
    @GetMapping("login")
    public String genQrConnect(HttpSession session) {
        String baseUri = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        // 处理回调url
        String redirectUri = "";
        try {
            redirectUri = URLEncoder.encode(ucenterProperties.getRedirectUri(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(ExceptionUtils.getStackTrace(e));
            throw new GuLiException(ResultCodeEnum.URL_ENCODE_ERROR);
        }
        // 处理state: 生成随机数,存入session
        String state = UUID.randomUUID().toString();
        System.out.println("生成stats= " + state);
        session.setAttribute("wx_open_state", state);

        // 按顺序填充指定字符串
        String qrcodeUrl = String.format(baseUri, ucenterProperties.getAppId(), redirectUri, state, ucenterProperties.getAppSecret());
        return "redirect:" + qrcodeUrl;
    }

    @GetMapping("callback")
    public String callback(String code, String state, HttpSession session) {
        //回调被拉起，并获得code和state参数
        System.out.println("callback被调用");
        System.out.println("code = " + code);
        System.out.println("state = " + state);

        // 一 校验code和state
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
            log.error("非法回调请求");
            throw new GuLiException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        // 判断url中的state与session是否一致  从session获取state
        String checkState = (String) session.getAttribute("wx_open_state");
        if (!state.equals(checkState)) {
            log.error("非法回调请求");
            throw new GuLiException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }

        //二 携带授权临时票据code，和appid以及appsecret获取access_token
        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
        Map<String, String> accessTokenParam = new HashMap<>();
        accessTokenParam.put("appid", ucenterProperties.getAppId());
        accessTokenParam.put("secret", ucenterProperties.getAppSecret());
        accessTokenParam.put("code", code);
        accessTokenParam.put("grant_type", "authorization_code");
        //在url中组装参数
        HttpClientUtils client = new HttpClientUtils(accessTokenUrl, accessTokenParam);

        //三 携带access_token获取用户信息
        String result = "";
        try {
            client.setHttps(true);  //设置为https协议
            client.get(); //发送get请求
            result = client.getContent(); //获取accessToken
            System.out.println("result = " + result);
        } catch (Exception e) {
            log.error("获取access_token失败" + ExceptionUtils.getStackTrace(e));
            throw new GuLiException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        // 将json字符串结果转成map
        Gson gson = new Gson();
        HashMap<String, Object> resultMap = gson.fromJson(result, HashMap.class);

        //判断微信获取access_token失败的响应
        Object errcodeObj = resultMap.get("errcode");
        if (errcodeObj != null) {
            String errmsg = (String) resultMap.get("errmsg");
            Double errcode = (Double) errcodeObj;
            log.error("获取access_token失败 - " + "message: " + errmsg + ", errcode: " + errcode);
            throw new GuLiException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        //微信获取access_token响应成功
        String accessToken = (String) resultMap.get("access_token");
        String openid = (String) resultMap.get("openid");
        System.out.println("accessToken = " + accessToken);
        System.out.println("openid = " + openid);

        //四 根据access_token获取微信用户的基本信息
        // 根据openid查询当前用户是否已经使用微信登录过该系统
        Member member = memberService.getByOpenid(openid);
        if (member == null) {
            //向微信的资源服务器发起请求，获取当前用户的用户信息
            String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?" +
                    "access_token=" + accessToken +
                    "&openid=" + openid;
            client = new HttpClientUtils(userInfoUrl);
            String resultUserInfo = null;
            try {
                client.setHttps(true);
                client.get();
                resultUserInfo = client.getContent();
            } catch (Exception e) {
                log.error("获取用户信息失败 " + ExceptionUtils.getStackTrace(e));
                throw new GuLiException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }

            // 解析json字符串
            HashMap<String,Object> resultMapUserInfo = gson.fromJson(resultUserInfo, HashMap.class);
            //失败参数信息
            if(resultMapUserInfo.get("errcode") != null){
                log.error("获取用户信息失败" + "，message：" + resultMap.get("errmsg"));
                throw new GuLiException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }

            //成功参数信息
            String nickname = (String) resultMapUserInfo.get("nickname");
            String headimgurl = (String) resultMapUserInfo.get("headimgurl");
            Double sex = (Double) resultMapUserInfo.get("sex");

            //将用户信息插入到数据库，完成用户注册
            member = new Member();
            member.setOpenid(openid);
            member.setNickname(nickname);
            member.setAvatar(headimgurl);
            member.setSex(sex.intValue());
            memberService.save(member);
        }

        //五 生成jwt完成用户登录
        JwtInfo jwtInfo = new JwtInfo();
        jwtInfo.setId(member.getId());
        jwtInfo.setAvatar(member.getAvatar());
        jwtInfo.setNickname(member.getNickname());
        String token = JwtHelper.createToken(jwtInfo);

        //携带token跳转到首页
        return "redirect:http://localhost:3000?token=" + token;
    }
}
